
//
// 110619 - AH - Created.
// 110728 - AH - (Bybanen *) Missing java doc.
//

package org.soekrat.engine.io.xmlutil;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;


/**
 * <p>
 *   Administer generation of XML by use of 
 *   {@link XmlTopContentGenerator} and
 *   {@link XmlContentGenerator}.
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC)
 */
public final class XmlGenerator
{
  private XmlTopContentGenerator m_tcg=null;
  
  private XmlContentGenerator m_cg=null;
  
  private PrintWriter m_pw=null;
  
  /**
   * <p>
   *   Constructor.
   * </p>
   */
  public XmlGenerator(){}
  
  /**
   * <p>
   *   Sets 
   *   {@link XmlTopContentGenerator} to use.
   * </p>
   * @param top {@code XmlTopContentGenerator} to use.
   * @return {@code this}.
   */
  public XmlGenerator setXmlTopContentGenerator(XmlTopContentGenerator tcg)
  {
    if (tcg==null)
    {
      throw new NullPointerException("tcg");
    }
    
    m_tcg=tcg;
    return this;
  }
  
  /**
   * <p>
   *   Gets 
   *   {@link XmlTopContentGenerator} used.
   * </p>
   * @return {@link XmlTopContentGenerator} or {@code null} if none sat.
   */
  public XmlTopContentGenerator getXmlTopContentGenerator(){ return m_tcg; }
  
  /**
   * <p>
   *   Sets 
   *   {@link XmlContentGenerator} to use.
   * </p>
   * @param cg {@link XmlContentGenerator} to use.
   * @return {@code this}.
   */
  public XmlGenerator setXmlContentGenerator(XmlContentGenerator cg)
  {
    if (cg==null)
    {
      throw new NullPointerException("cg");
    }
    
    m_cg=cg;
    return this;
  }
  
  /**
   * <p>
   *   Gets
   *   {@link XmlContentGenerator} used.
   * </p>
   * @return {@link XmlContentGenerator}.
   */
  public XmlContentGenerator getXmlContentGenerator(){ return m_cg; }
 
  /**
   * <p>
   *   Starts writing XML.
   * </p>
   * @param os Stream to write to.
   * @throws IllegalStateException If already is writing to stream.
   * @throws IllegalStateException If 
   *                               {@link XmlTopContentGenerator} not defined. 
   */
  public void start(OutputStream os)
  {
    if (os==null)
    {
      throw new NullPointerException("os");
    }
    
    start(new PrintWriter(os));
  }
  
  /**
   * <p>
   *   Starts writing XML.
   * </p>
   * @param f {@link File} to write to.
   * @throws IllegalStateException If already is writing to stream.
   * @throws IllegalStateException If 
   *                               {@link XmlTopContentGenerator} not defined.
   * @throws IOException If fails to open file. 
   */
  public void start(File f) throws IOException
  {
    if (f==null)
    {
      throw new NullPointerException("f");
    }
    
    start(new PrintWriter(f));
  }
  
  /**
   * <p>
   *   Starts writing XML.
   * </p>
   * @param pw Stream to write to.
   * @throws IllegalStateException If already is writing to stream.
   * @throws IllegalStateException If 
   *                               {@link XmlTopContentGenerator} not defined. 
   */
  public void start(PrintWriter pw)
  {
    if (pw==null)
    {
      throw new NullPointerException("pw");
    }
    
    if (m_pw!=null)
    {
      throw new IllegalStateException("Has stream");
    }
    
    if (m_tcg==null)
    {
      throw new IllegalStateException("Missing XmlTopContentGenerator");
    }
    
    String start=m_tcg.getStart();
    
    pw.println(start);
    pw.flush();
    
    m_pw=pw;
  }
  
  /**
   * <p>
   *   Writes XML.
   * </p>
   * @param o Object to write XML for.
   * @throws IllegalStateException If a {@code start} has not set stream to
   *         write to.
   * @throws IllegalStateException If 
   *                               {@link XmlContentGenerator} not defined. 
   */
  public void write(Object o)
  {
    if (m_cg==null)
    {
      throw new IllegalStateException("Missing XmlContentGenerator");
    }
    
    m_pw.println(m_cg.compile(o));
  }
  
  /**
   * <p>
   *   Finish writing XML.
   * </p>
   * <p>
   *   Further call to this method or
   *   {@link #write(Object)} will cause a
   *   {@link IllegalStateException} to be thrown until a successful call to a
   *   start method has been done.
   * </p>
   * @throws IllegalStateException If a {@code start} has not set stream to
   *         write to.
   * @throws IllegalStateException If 
   *                               {@link XmlTopContentGenerator} not defined. 
   */
  public void end()
  {
    if (m_pw==null)
    {
      throw new IllegalStateException("Missing stream");
    }
    
    if (m_tcg==null)
    {
      throw new IllegalStateException("Missing XmlTopContentGenerator");
    }
    
    m_pw.println(m_tcg.getEnd());
    m_pw.flush();
    m_pw.close();
    m_pw=null;
  }
  
}
